<template>
  <div class="dialog-editor">
    <div class="editor-layout">
      <!-- 左侧：图片上传与展示 -->
      <div class="left-panel">
        <el-upload
          class="upload-demo"
          :show-file-list="false"
          :on-change="handleImageChange"
          accept="image/*"
          :auto-upload="false"
        >
          <el-button type="primary">上传漫画图片</el-button>
        </el-upload>

        <el-button type="primary" @click="exportImage">导出图片</el-button>

        <!-- 漫画容器 -->
        <div class="comic-container" id="export-content" ref="comicContainerRef">
          <img :src="comicImage" alt="Comic" v-if="comicImage" class="comic-image" />

          <!-- 预设图片区域 -->
          <div
            v-for="(image, index) in presetImages"
            :key="'preset-' + index"
            class="preset-image"
            :style="{
              position: 'absolute',
              top: image.y + 'px',
              left: image.x + 'px',
              width: image.width + 'px',
              height: image.height + 'px',
              zIndex: image.zIndex || 1, /* 设置预设图片的层级，默认值为1 */
            }"
            @mousedown="startDrag($event, index, 'preset')"
          >
            <img
              :src="image.src"
              alt="Preset Image"
              class="preset-img"
              :style="{
                width: image.width + 'px',
                height: image.height + 'px',
              }"
            />
          </div>

          <!-- 对话框区域 -->
          <div
            v-for="(dialog, index) in dialogs"
            :key="index"
            class="dialog-box"
            :style="{
              top: dialog.y + 'px',
              left: dialog.x + 'px',
              width: dialog.width + 'px',
              height: dialog.height + 'px',
              color: dialog.textColor,
              backgroundColor: dialog.bgColor,
              backgroundImage: `url(${dialog.bgImageUrl})`,
              backgroundSize: 'cover',
              fontSize: 'initial',
              zIndex: dialog.zIndex || 2, /* 设置对话框的层级，默认值为2 */
            }"
            @mousedown="startDrag($event, index, 'dialog')"
          >
            {{ dialog.text }}
          </div>

          <!-- 纯文本区域 -->
          <div
            v-for="(text, index) in texts"
            :key="index"
            class="text-only"
            :style="{
              top: text.y + 'px',
              left: text.x + 'px',
              width: text.width + 'px',
              height: text.height + 'px',
              color: text.textColor,
              fontSize: '16px',
              backgroundImage: `url(${text.bgImageUrl})`,
              backgroundSize: 'cover',
              border: 'none',
              padding: '0',
              zIndex: text.zIndex || 3, /* 设置纯文本的层级，默认值为3 */
            }"
            @mousedown="startDrag($event, index, 'text')"
          >
            {{ text.text }}
          </div>
        </div>
      </div>

      <!-- 右侧：对话框与文本编辑器 -->
      <div class="right-panel">
        <!-- 添加对话框 -->
        <el-input v-model="newDialogText" placeholder="输入对话框文本"></el-input>
        <el-button type="primary" @click="addDialog">添加对话框</el-button>

        <!-- 添加纯文本 -->
        <el-input v-model="newText" placeholder="输入纯文本"></el-input>
        <el-button type="primary" @click="addText">添加纯文本</el-button>

        <!-- 预设图片尺寸控制 -->
        <div class="preset-images-section">
          <h3>预设图片</h3>
          <el-input v-model="customWidth" placeholder="输入图片宽度" style="width: 100%; margin-bottom: 10px;"></el-input>
          <el-input v-model="customHeight" placeholder="输入图片高度" style="width: 100%; margin-bottom: 20px;"></el-input>
          <el-button
            v-for="(image, index) in availablePresetImages"
            :key="'preset-btn-' + index"
            type="primary"
            @click="addPresetImage(image)"
          >
            选择图片 {{ index + 1 }}
          </el-button>
        </div>

        <!-- 预设图片列表 -->
        <el-table :data="presetImages" style="margin-top: 20px;">
          <el-table-column label="预设图片" width="150">
            <template v-slot="scope">
              <img
                :src="scope.row.src"
                alt="Preset Image"
                class="preset-img"
                style="width: 100px; height: 100px;"
              />
            </template>
          </el-table-column>
          <el-table-column label="操作" width="100">
            <template v-slot="scope">
              <el-button
                type="danger"
                size="mini"
                @click="deletePresetImage(scope.$index)"
                >删除</el-button>
            </template>
          </el-table-column>
        </el-table>

        <!-- 显示对话框列表 -->
        <el-table :data="dialogs" style="margin-top: 20px;">
          <el-table-column prop="text" label="文本" width="150"></el-table-column>
          <el-table-column prop="x" label="X坐标" width="80"></el-table-column>
          <el-table-column prop="y" label="Y坐标" width="80"></el-table-column>
          <el-table-column prop="width" label="宽度" width="80"></el-table-column>
          <el-table-column prop="height" label="高度" width="80"></el-table-column>
          <el-table-column label="操作" width="100">
            <template v-slot="scope">
              <el-button
                type="danger"
                size="mini"
                @click="deleteDialog(scope.$index)"
                >删除</el-button>
            </template>
          </el-table-column>
        </el-table>

        <!-- 显示纯文本列表 -->
        <el-table :data="texts" style="margin-top: 20px;">
          <el-table-column prop="text" label="文本" width="150"></el-table-column>
          <el-table-column prop="x" label="X坐标" width="80"></el-table-column>
          <el-table-column prop="y" label="Y坐标" width="80"></el-table-column>
          <el-table-column prop="width" label="宽度" width="80"></el-table-column>
          <el-table-column prop="height" label="高度" width="80"></el-table-column>
          <el-table-column label="操作" width="100">
            <template v-slot="scope">
              <el-button
                type="danger"
                size="mini"
                @click="deleteText(scope.$index)"
                >删除</el-button>
            </template>
          </el-table-column>
        </el-table>
      </div>
    </div>
  </div>
</template>

  
  

  <script>
  import { ref } from 'vue';
  import html2canvas from 'html2canvas'; // 引入 html2canvas
  import { ElUpload, ElButton, ElInput, ElTable, ElTableColumn } from 'element-plus';


  export default {
    components: {
      ElUpload,
      ElButton,
      ElInput,
      ElTable,
      ElTableColumn,
    },
    setup() {
      const comicImage = ref('');  // 存储漫画图片
      const dialogs = ref([]);  // 存储对话框
      const texts = ref([]);  // 存储纯文本
      const presetImages = ref([]);  // 存储拖动到页面的预设图片
      const newDialogText = ref('');  // 新对话框文本
      const newText = ref('');  // 新纯文本

      const customWidth = ref(100);  // 用于控制预设图片宽度
      const customHeight = ref(100);  // 用于控制预设图片高度

      // 预设图片资源
      const availablePresetImages = ref([
        { src: '/assets/bg1.png' },
        { src: '/assets/bg2.png' },
        { src: '/assets/bg1.png' },
      ]);

      // 导出图片
      const exportImage = () => {
        const exportElement = document.getElementById('export-content'); // 选择要导出的 DOM 元素

        html2canvas(exportElement, {
          useCORS: true, // 解决跨域问题
          scale: 2, // 提高导出图片分辨率
          allowTaint: false, // 不允许使用污染画布
          logging: true, // 开启日志记录以便调试
          letterRendering: 1, // 使用清晰的文字渲染
          scrollX: 0, // 设置滚动条的位置
          scrollY: 0, // 设置滚动条的位置
        }).then((canvas) => {
          // 将 canvas 转换为图片并触发下载
          const dataURL = canvas.toDataURL('image/png'); // 获取 base64 格式的 PNG 图像

          const link = document.createElement('a'); // 创建下载链接
          link.href = dataURL;
          link.download = 'exported_comic.png'; // 设置下载文件名
          link.click(); // 触发下载
        }).catch((error) => {
          console.error('导出图片时发生错误:', error);
        });
      };

      // 处理图片上传
      const handleImageChange = (file, fileList) => {
        if (file && file.raw) {
          const reader = new FileReader();
          reader.onload = (e) => {
            comicImage.value = e.target.result;
          };
          reader.readAsDataURL(file.raw);
        }
      };

      // 添加预设图片
      const addPresetImage = (image) => {
        presetImages.value.push({
          src: image.src,
          x: Math.random() * 200,
          y: Math.random() * 200,
          width: customWidth.value,  // 使用自定义的宽度
          height: customHeight.value,  // 使用自定义的高度
        });
      };

      // 删除预设图片
      const deletePresetImage = (index) => {
        presetImages.value.splice(index, 1);
      };

      // 添加对话框
      const addDialog = () => {
        if (newDialogText.value.trim()) {
          dialogs.value.push({
            text: newDialogText.value,
            x: Math.random() * 200,
            y: Math.random() * 200,
            width: 100,
            height: 50,
            textColor: '#000',
            bgColor: 'transparent',
            bgImageUrl: '',
          });
          newDialogText.value = '';
        }
      };

      // 添加纯文本
      const addText = () => {
        if (newText.value.trim()) {
          texts.value.push({
            text: newText.value,
            x: Math.random() * 200,
            y: Math.random() * 200,
            width: 100,
            height: 50,
            textColor: '#000',
            bgImageUrl: '',
          });
          newText.value = '';
        }
      };

      // 删除对话框
      const deleteDialog = (index) => {
        dialogs.value.splice(index, 1);
      };

      // 删除纯文本
      const deleteText = (index) => {
        texts.value.splice(index, 1);
      };

      // 拖动功能
      const startDrag = (event, index, type) => {
        let offsetX = event.clientX - event.target.offsetLeft;
        let offsetY = event.clientY - event.target.offsetTop;

        const onMouseMove = (e) => {
          let newX = e.clientX - offsetX;
          let newY = e.clientY - offsetY;

          if (type === 'dialog') {
            dialogs.value[index].x = newX;
            dialogs.value[index].y = newY;
          } else if (type === 'text') {
            texts.value[index].x = newX;
            texts.value[index].y = newY;
          } else if (type === 'preset') {
            presetImages.value[index].x = newX;
            presetImages.value[index].y = newY;
          }
        };

        const onMouseUp = () => {
          document.removeEventListener('mousemove', onMouseMove);
          document.removeEventListener('mouseup', onMouseUp);
        };

        document.addEventListener('mousemove', onMouseMove);
        document.addEventListener('mouseup', onMouseUp);
      };

      return {
        comicImage,
        dialogs,
        texts,
        presetImages,
        newDialogText,
        newText,
        availablePresetImages,
        customWidth,
        customHeight,
        handleImageChange,
        addPresetImage,
        deletePresetImage,
        addDialog,
        addText,
        deleteDialog,
        deleteText,
        startDrag,
        exportImage,
      };
    },
  };
</script>


  
  
  
  <style scoped>
/* 定义基本的颜色、字体等变量 */
:root {
  --primary-color: #409EFF; /* Element Plus primary color */
  --text-color: #333; /* 默认文本颜色 */
  --bg-color-light: #f5f5f5; /* 背景颜色 */
  --dialog-bg-color: transparent;
  --border-radius: 8px; /* 圆角设置 */
  --padding: 10px; /* 基础内边距 */
  --font-size-small: 14px; /* 小号字体 */
  --font-size-medium: 16px; /* 中号字体 */
  --font-size-large: 18px; /* 大号字体 */
}

body, html {
  margin: 0;
  padding: 0;
  height: 100%; /* 确保body和html占满全高 */
  font-family: 'Arial', sans-serif;
  background-color: var(--bg-color-light);
}

/* 使整个页面的布局充满高度 */
.dialog-editor {
  display: flex;
  justify-content: space-between;
  padding: 20px;
  height: 100vh; /* 使父容器的高度充满整个视口 */
}

.editor-layout {
  display: flex;
  flex: 1;
  flex-direction: row;
  gap: 20px;
  height: 100%; /* 让子元素充满父容器 */
}

.left-panel {
  flex: 6; /* 60% */
  padding: var(--padding);
  background-color: #fff;
  border-radius: var(--border-radius);
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
  overflow-y: auto; /* 确保内容超过时可滚动 */
}

.right-panel {
  flex: 4; /* 40% */
  padding: var(--padding);
  background-color: #fff;
  border-radius: var(--border-radius);
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
  overflow-y: auto; /* 保证内容超出时可以滚动 */
}

/* 图片上传按钮样式 */
.upload-demo .el-button {
  margin-bottom: 15px;
}

.comic-container {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
  background-color: #eaeaea; /* 背景色 */
  border-radius: var(--border-radius);
  display: flex;
  align-items: center; /* 垂直居中 */
  justify-content: center; /* 水平居中 */
}

.comic-image {
  width: auto;
  height: 50vh; /* 图片高度占据屏幕的一半 */
  max-width: 100%; /* 最大宽度为100% */
  object-fit: contain; /* 保持图片的宽高比 */
  border-radius: var(--border-radius);
}

/* 对话框与文本样式 */
.dialog-box, .text-only {
  position: absolute;
  padding: var(--padding);
  border-radius: var(--border-radius);
  color: var(--text-color);
  background-color: var(--dialog-bg-color);
  font-size: var(--font-size-small);
  text-align: center;
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
  cursor: move;
}

.text-only {
  font-size: var(--font-size-small);
  background-size: cover;
}

.preset-image {
  position: absolute;
  cursor: move;
  transition: all 0.3s ease;
}

.preset-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* 右侧面板 */
.el-input {
  margin-bottom: 15px;
}

.el-button {
  margin-top: 10px;
}

.preset-images-section {
  margin-bottom: 20px;
}

.preset-images-section h3 {
  margin-bottom: 10px;
  font-size: var(--font-size-large);
  color: var(--text-color);
}

.el-table {
  margin-top: 20px;
}

.el-table th, .el-table td {
  padding: 10px;
  text-align: center;
}

.el-button[type="danger"] {
  background-color: #f56c6c;
  border-color: #f56c6c;
}

.el-button[type="danger"]:hover {
  background-color: #e04343;
  border-color: #e04343;
}

/* 对话框和文本框拖拽效果 */
.dialog-box, .text-only, .preset-image {
  transition: transform 0.2s ease;
}

.dialog-box:hover, .text-only:hover, .preset-image:hover {
  transform: scale(1.05);
}

/* 响应式布局 */
@media screen and (max-width: 768px) {
  .editor-layout {
    flex-direction: column;
    height: 100%; /* 确保在小屏幕下也充满高度 */
  }

  .left-panel, .right-panel {
    max-width: 100%;
    padding: 10px;
  }

  .comic-container {
    height: 300px; /* 在小屏幕下，调整漫画容器的高度 */
  }

  .comic-image {
    max-height: 300px; /* 限制图片的最大高度 */
  }
}

@media screen and (max-width: 480px) {
  .preset-images-section h3 {
    font-size: var(--font-size-medium);
  }

  .el-button {
    width: 100%; /* 调整按钮在小屏幕下的宽度 */
  }
}

  </style>
  